package org.nf.web.invoke;

import cn.hutool.core.util.ReflectUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.nf.web.common.TypeConvertor;
import org.nf.web.servlet.HandlerInvoke;
import org.nf.web.servlet.MethodArgumentsResolver;
import org.nf.web.servlet.ServletApi;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ServiceLoader;

/**
 * @author zhu
 * @date 2024-05-15
 */
public class MethodHandlerInvoke implements HandlerInvoke {

    private static final ServiceLoader<MethodArgumentsResolver> LOADER = ServiceLoader.load(MethodArgumentsResolver.class);

    @Override
    public Object invoke(Object handler, ServletApi servletApi) throws Exception {
        // 将handler强转为method对象
        Method method = (Method) handler;
        Object[] params = resolveMethodArguments(method,servletApi);
        // 创建Controller的实例
        Object instance = ReflectUtil.newInstance(method.getDeclaringClass());
        // 调用方法,并将请求和响应对象传给方法
        return method.invoke(instance, params);
    }

    @Override
    public boolean supports(Object obj) {
        //如果当前的handler是Method的实例则返回true
        return obj instanceof Method;
    }

    /**
     * 解析方法参数，并转换为Object[]返回
     *
     * @param method 处理请求的方法
     * @param servletApi 请求对象和响应对象
     * @return 返回解析好的参数内容
     */
    private Object[] resolveMethodArguments(Method method, ServletApi servletApi) {
        Parameter[] params = method.getParameters();
        Object[] values = new Object[params.length];
        for (int i = 0; i < params.length; i++) {
            Parameter param = params[i];
            for(MethodArgumentsResolver resolver : LOADER) {
                if (resolver.supports(param)) {
                    values[i] = resolver.resolve(param, servletApi);
                    break;
                }
            }
        }
        return values;
    }
}
